home *** CD-ROM | disk | FTP | other *** search
/ Revista do CD-ROM 97 / CD-ROM 97 / CD-ROM 97.iso / internet / ghostzilla / ghsetup.exe / chrome / chatzilla.jar / content / chatzilla / lib / js / utils.js < prev   
Encoding:
JavaScript  |  2002-04-09  |  13.9 KB  |  642 lines

  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2.  *
  3.  * The contents of this file are subject to the Mozilla Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/MPL/
  7.  *
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  *
  13.  * The Original Code is JSIRC Library
  14.  *
  15.  * The Initial Developer of the Original Code is New Dimensions Consulting,
  16.  * Inc. Portions created by New Dimensions Consulting, Inc. are
  17.  * Copyright (C) 1999 New Dimenstions Consulting, Inc. All
  18.  * Rights Reserved.
  19.  *
  20.  * Contributor(s): 
  21.  *
  22.  *
  23.  * Contributor(s):
  24.  *  Robert Ginda, rginda@ndcico.com, original author
  25.  *
  26.  *
  27.  * JavaScript utility functions.
  28.  *
  29.  * 1999-08-15 rginda@ndcico.com           v1.0
  30.  */
  31.  
  32. var DEBUG = true;
  33.  
  34. var dumpln;
  35. var dd;
  36.  
  37. if (typeof document == "undefined") /* in xpcshell */
  38.     dumpln = print;
  39. else
  40.     if (typeof dump == "function")
  41.         dumpln = function (str) {dump (str + "\n");}
  42.     else if (jsenv.HAS_RHINO)
  43.         dumpln = function (str) {var out = java.lang.System.out;
  44.                                  out.println(str); out.flush(); }
  45.     else
  46.         dumpln = function () {} /* no suitable function */
  47.  
  48. if (DEBUG)
  49.     dd = dumpln;
  50. else
  51.     dd = function (){};
  52.  
  53. var jsenv = new Object();
  54. jsenv.HAS_SECURITYMANAGER = ((typeof netscape == "object") &&
  55.                              (typeof netscape.security == "object"));
  56. jsenv.HAS_XPCOM = ((typeof Components == "object") &&
  57.                    (typeof Components.classes == "object"));
  58. jsenv.HAS_JAVA = (typeof java == "object");
  59. jsenv.HAS_RHINO = (typeof defineClass == "function");
  60. jsenv.HAS_DOCUMENT = (typeof document == "object");
  61. jsenv.HAS_NSPR_EVENTQ = jsenv.HAS_DOCUMENT;
  62.  
  63. function dumpObject (o, pfx, sep)
  64. {
  65.     var p;
  66.     var s = "";
  67.  
  68.     sep = (typeof sep == "undefined") ? " = " : sep;
  69.     pfx = (typeof pfx == "undefined") ? "" : pfx;    
  70.  
  71.     for (p in o)
  72.     {
  73.         if (typeof (o[p]) != "function")
  74.             s += pfx + p + sep + o[p] + "\n";
  75.         else
  76.             s += pfx + p + sep + "function\n";
  77.     }
  78.  
  79.     return s;
  80.  
  81. }
  82.  
  83. /* Dumps an object in tree format, recurse specifiec the the number of objects
  84.  * to recurse, compress is a boolean that can uncompress (true) the output
  85.  * format, and level is the number of levels to intitialy indent (only useful
  86.  * internally.)  A sample dumpObjectTree (o, 1) is shown below.
  87.  *
  88.  * + parent (object)
  89.  * + users (object)
  90.  * | + jsbot (object)
  91.  * | + mrjs (object)
  92.  * | + nakkezzzz (object)
  93.  * | *
  94.  * + bans (object)
  95.  * | *
  96.  * + topic (string) 'ircclient.js:59: nothing is not defined'
  97.  * + getUsersLength (function) 9 lines
  98.  * *
  99.  */
  100. function dumpObjectTree (o, recurse, compress, level)
  101. {
  102.     var s = "";
  103.     var pfx = "";
  104.  
  105.     if (typeof recurse == "undefined")
  106.         recurse = 0;
  107.     if (typeof level == "undefined")
  108.         level = 0;
  109.     if (typeof compress == "undefined")
  110.         compress = true;
  111.     
  112.     for (var i = 0; i < level; i++)
  113.         pfx += (compress) ? "| " : "|  ";
  114.  
  115.     var tee = (compress) ? "+ " : "+- ";
  116.  
  117.     for (i in o)
  118.     {
  119.         var t, ex;
  120.         
  121.         try
  122.         {
  123.             t = typeof o[i];
  124.         }
  125.         catch (ex)
  126.         {
  127.             t = "ERROR";
  128.         }
  129.         
  130.         switch (t)
  131.         {
  132.             case "function":
  133.                 var sfunc = String(o[i]).split("\n");
  134.                 if (sfunc[2] == "    [native code]")
  135.                     sfunc = "[native code]";
  136.                 else
  137.                     if (sfunc.length == 1)
  138.                         sfunc = String(sfunc);
  139.                     else
  140.                         sfunc = sfunc.length + " lines";
  141.                 s += pfx + tee + i + " (function) " + sfunc + "\n";
  142.                 break;
  143.  
  144.             case "object":
  145.                 s += pfx + tee + i + " (object)\n";
  146.                 if (!compress)
  147.                     s += pfx + "|\n";
  148.                 if ((i != "parent") && (recurse))
  149.                     s += dumpObjectTree (o[i], recurse - 1,
  150.                                          compress, level + 1);
  151.                 break;
  152.  
  153.             case "string":
  154.                 if (o[i].length > 200)
  155.                     s += pfx + tee + i + " (" + t + ") " + 
  156.                         o[i].length + " chars\n";
  157.                 else
  158.                     s += pfx + tee + i + " (" + t + ") '" + o[i] + "'\n";
  159.                 break;
  160.  
  161.             case "ERROR":
  162.                 s += pfx + tee + i + " (" + t + ") ?\n";
  163.                 break;
  164.                 
  165.             default:
  166.                 s += pfx + tee + i + " (" + t + ") " + o[i] + "\n";
  167.                 
  168.         }
  169.  
  170.         if (!compress)
  171.             s += pfx + "|\n";
  172.  
  173.     }
  174.  
  175.     s += pfx + "*\n";
  176.     
  177.     return s;
  178.     
  179. }
  180.  
  181. /*
  182.  * Clones an existing object (Only the enumerable properties
  183.  * of course.) use as a function..
  184.  * var c = Clone (obj);
  185.  * or a constructor...
  186.  * var c = new Clone (obj);
  187.  */
  188. function Clone (obj)
  189. {
  190.     robj = new Object();
  191.  
  192.     for (var p in obj)
  193.         robj[p] = obj[p];
  194.  
  195.     return robj;
  196.     
  197. }
  198.  
  199. /*
  200.  * matches a real object against one or more pattern objects.
  201.  * if you pass an array of pattern objects, |negate| controls wether to check
  202.  * if the object matches ANY of the patterns, or NONE of the patterns.
  203.  */
  204. function matchObject (o, pattern, negate)
  205. {
  206.     negate = Boolean(negate);
  207.     
  208.     function _match (o, pattern)
  209.     {
  210.         if (pattern instanceof Function)
  211.             return pattern(o);
  212.         
  213.         for (p in pattern)
  214.         {
  215.             var val;
  216.                 /* nice to have, but slow as molases, allows you to match
  217.                  * properties of objects with obj$prop: "foo" syntax      */
  218.                 /*
  219.                   if (p[0] == "$")
  220.                   val = eval ("o." + 
  221.                   p.substr(1,p.length).replace (/\$/g, "."));
  222.                   else
  223.                 */
  224.             val = o[p];
  225.             
  226.             if (pattern[p] instanceof Function)
  227.             {
  228.                 if (!pattern[p](val))
  229.                     return false;
  230.             }
  231.             else
  232.             {
  233.                 var ary = (new String(val)).match(pattern[p]);
  234.                 if (ary == null)
  235.                     return false;
  236.                 else
  237.                     o.matchresult = ary;
  238.             }
  239.         }
  240.  
  241.         return true;
  242.  
  243.     }
  244.  
  245.     if (!(pattern instanceof Array))
  246.         return Boolean (negate ^ _match(o, pattern));
  247.             
  248.     for (var i in pattern)
  249.         if (_match (o, pattern[i]))
  250.             return !negate;
  251.  
  252.     return negate;
  253.     
  254. }
  255.  
  256. function matchEntry (partialName, list)
  257. {
  258.     
  259.     if ((typeof partialName == "undefined") ||
  260.         (String(partialName) == ""))
  261.         return list;
  262.  
  263.     var ary = new Array();
  264.  
  265.     for (var i in list)
  266.     {
  267.         if (list[i].indexOf(partialName) == 0)
  268.             ary.push (list[i]);
  269.     }
  270.  
  271.     return ary;
  272.     
  273. }
  274.  
  275. function getCommonPfx (list)
  276. {
  277.     var pfx = list[0];
  278.     var l = list.length;
  279.     
  280.     for (var i = 0; i < l; i++)
  281.     {
  282.         for (var c = 0; c < pfx.length; ++c)
  283.         {
  284.             if (c >= list[i].length)
  285.             {
  286.                 pfx = pfx.substr (0, c);
  287.                 break;
  288.             }
  289.             else
  290.             {
  291.                 if (pfx[c] != list[i][c])
  292.                     pfx = pfx.substr (0, c);
  293.             }
  294.         }
  295.     }
  296.  
  297.     return pfx;
  298.  
  299. }
  300.  
  301. function renameProperty (obj, oldname, newname)
  302. {
  303.  
  304.     if (oldname == newname)
  305.         return;
  306.     
  307.     obj[newname] = obj[oldname];
  308.     delete obj[oldname];
  309.     
  310. }
  311.  
  312. function newObject(contractID, iface)
  313. {
  314.     if (!jsenv.HAS_XPCOM)
  315.         return null;
  316.  
  317.     var obj = Components.classes[contractID].createInstance();
  318.     var rv;
  319.  
  320.     switch (typeof iface)
  321.     {
  322.         case "string":
  323.             rv = obj.QueryInterface(Components.interfaces[iface]);
  324.             break;
  325.  
  326.         case "object":
  327.             rv = obj.QueryInterface[iface];
  328.             break;
  329.  
  330.         default:
  331.             rv = null;
  332.             break;
  333.     }
  334.  
  335.     return rv;
  336.     
  337. }
  338.  
  339. function getPriv (priv)
  340. {
  341.     if (!jsenv.HAS_SECURITYMANAGER)
  342.         return true;
  343.  
  344.     var rv = true;
  345.  
  346.     try
  347.     {
  348.         netscape.security.PrivilegeManager.enablePrivilege(priv);
  349.     }
  350.     catch (e)
  351.     {
  352.         dd ("getPriv: unable to get privlege '" + priv + "': " + e);
  353.         rv = false;
  354.     }
  355.     
  356.     return rv;
  357.     
  358. }
  359.  
  360. function keys (o)
  361. {
  362.     var rv = new Array();
  363.     
  364.     for (var p in o)
  365.         rv.push(p);
  366.  
  367.     return rv;
  368.     
  369. }
  370.  
  371. function stringTrim (s)
  372. {
  373.     if (!s)
  374.         return "";
  375.     s = s.replace (/^\s+/, "");
  376.     return s.replace (/\s+$/, "");
  377.     
  378. }
  379.  
  380. /* the offset should be in seconds, it will be rounded to 2 decimal places */
  381. function formatDateOffset (offset, format)
  382. {
  383.     offset = roundTo(offset, 2);
  384.     var seconds = offset % 60;
  385.     var minutes = parseInt(offset / 60);
  386.     var hours = parseInt(minutes / 60);
  387.     minutes = minutes % 60;
  388.     var days = parseInt(hours / 24);
  389.     hours = hours % 24;
  390.  
  391.     if (!format)
  392.     {
  393.         var ary = new Array();
  394.         if (days > 0)
  395.             ary.push (days + " days");
  396.         if (hours > 0)
  397.             ary.push (hours + " hours");
  398.         if (minutes > 0)
  399.             ary.push (minutes + " minutes");
  400.         if (seconds > 0 || offset == 0)
  401.             ary.push (seconds + " seconds");
  402.  
  403.         format = ary.join(", ");
  404.     }
  405.     else
  406.     {
  407.         format = format.replace ("%d", days);
  408.         format = format.replace ("%h", hours);
  409.         format = format.replace ("%m", minutes);
  410.         format = format.replace ("%s", seconds);
  411.     }
  412.     
  413.     return format;
  414. }
  415.  
  416. function arrayContains (ary, elem)
  417. {
  418.     return (arrayIndexOf (ary, elem) != -1);
  419. }
  420.  
  421. function arrayIndexOf (ary, elem)
  422. {
  423.     for (var i in ary)
  424.         if (ary[i] == elem)
  425.             return i;
  426.  
  427.     return -1;
  428. }
  429.     
  430. function arrayInsertAt (ary, i, o)
  431. {
  432.  
  433.     ary.splice (i, 0, o);
  434.  
  435.     /* doh, forgot about that 'splice' thing
  436.     if (ary.length < i)
  437.     {
  438.         this[i] = o;
  439.         return;
  440.     }
  441.  
  442.     for (var j = ary.length; j > i; j--)
  443.         ary[j] = ary[j - 1];
  444.  
  445.     ary[i] = o;
  446.     */
  447. }
  448.  
  449. function arrayRemoveAt (ary, i)
  450. {
  451.  
  452.     ary.splice (i, 1);
  453.  
  454.     /* doh, forgot about that 'splice' thing
  455.     if (ary.length < i)
  456.         return false;
  457.  
  458.     for (var j = i; j < ary.length; j++)
  459.         ary[j] = ary[j + 1];
  460.  
  461.     ary.length--;
  462.     */
  463.  
  464. }
  465.  
  466. /* length should be an even number >= 6 */
  467. function abbreviateWord (str, length)
  468. {
  469.     if (str.length <= length || length < 6)
  470.         return str;
  471.  
  472.     var left = str.substr (0, (length / 2) - 1);
  473.     var right = str.substr (str.length - (length / 2) + 1);
  474.  
  475.     return left + "..." + right;
  476. }
  477.  
  478. /*
  479.  * Inserts the string |hyphen| into string |str| every |pos| characters.
  480.  * If there are any wordbreaking characters in |str| within -/+5 characters of
  481.  * of a |pos| then the hyphen is inserted there instead, in order to produce a
  482.  * "cleaner" break.
  483.  */
  484. function hyphenateWord (str, pos, hyphen)
  485. {
  486.     if (str.length <= pos)
  487.         return str;
  488.     if (typeof hyphen == "undefined")
  489.         hyphen = " ";
  490.  
  491.     /* search for a nice place to break the word, fuzzfactor of +/-5, centered
  492.      * around |pos| */
  493.     var splitPos =
  494.         str.substring(pos - 5, pos + 5).search(/[^A-Za-z0-9]/);
  495.  
  496.     splitPos = (splitPos != -1) ? pos - 4 + splitPos : pos;
  497.     var left = str.substr (0, splitPos);
  498.     var right = hyphenateWord(str.substr (splitPos), pos, hyphen);
  499.  
  500.     return left + hyphen + right;
  501. }
  502.  
  503. /*
  504.  * Like hyphenateWord, except individual chunks of the word are returned as
  505.  * elements of an array.
  506.  */
  507. function splitLongWord (str, pos)
  508. {
  509.     if (str.length <= pos)
  510.         return [str];
  511.  
  512.     var ary = new Array();
  513.     var right = str;
  514.     
  515.     while (right.length > pos)
  516.     {
  517.         /* search for a nice place to break the word, fuzzfactor of +/-5, 
  518.          * centered around |pos| */
  519.         var splitPos =
  520.             right.substring(pos - 5, pos + 5).search(/[^A-Za-z0-9]/);
  521.  
  522.         splitPos = (splitPos != -1) ? pos - 4 + splitPos : pos;
  523.         ary.push(right.substr (0, splitPos));
  524.         right = right.substr (splitPos);
  525.     }
  526.  
  527.     ary.push (right);
  528.  
  529.     return ary;
  530. }
  531.  
  532. function getRandomElement (ary)
  533. {
  534.  
  535.     return ary[Math.floor(Math.random() * ary.length)];
  536.  
  537. }
  538.  
  539. function roundTo (num, prec)
  540. {
  541.  
  542.     return Math.round(num * Math.pow (10, prec)) / Math.pow (10, prec);   
  543.  
  544. }
  545.  
  546. function randomRange (min, max)
  547. {
  548.  
  549.     if (typeof min == "undefined")
  550.         min = 0;
  551.  
  552.     if (typeof max == "undefined")
  553.         max = 1;
  554.  
  555.     return Math.floor(Math.random() * (max - min + 1)) + min;
  556.  
  557. }
  558.  
  559. function getStackTrace ()
  560. {
  561.  
  562.     if (!jsenv.HAS_XPCOM)
  563.         return "No stack trace available.";
  564.  
  565.     var frame = Components.stack.caller;
  566.     var str = "<top>";
  567.  
  568.     while (frame)
  569.     {
  570.         var name = frame.name ? frame.name : "[anonymous]";
  571.         str += "\n" + name + "@" + frame.lineNumber;
  572.         frame = frame.caller;
  573.     }
  574.  
  575.     return str;
  576.     
  577. }
  578.  
  579. function getInterfaces (cls)
  580. {
  581.     if (!jsenv.HAS_XPCOM)
  582.         return null;
  583.  
  584.     var rv = new Object();
  585.     var e;
  586.  
  587.     for (var i in Components.interfaces)
  588.     {
  589.         try
  590.         {
  591.             var ifc = Components.interfaces[i];
  592.             cls.QueryInterface(ifc);
  593.             rv[i] = ifc;
  594.         }
  595.         catch (e)
  596.         {
  597.             /* nada */
  598.         }
  599.     }
  600.  
  601.     return rv;
  602.     
  603. }
  604.  
  605. /**
  606.  * Calls a named function for each element in an array, sending
  607.  * the same parameter each call.
  608.  *
  609.  * @param ary           an array of objects
  610.  * @param func_name     string name of function to call.
  611.  * @param data          data object to pass to each object.
  612.  */      
  613. function mapObjFunc(ary, func_name, data)
  614. {
  615.     /* 
  616.      * WARNING: Caller assumes resonsibility to verify ary
  617.      * and func_name
  618.      */
  619.  
  620.     for (var i in ary)
  621.         ary[i][func_name](data);
  622. }
  623.  
  624. /**
  625.  * Passes each element of an array to a given function object.
  626.  *
  627.  * @param func  a function object.
  628.  * @param ary   an array of values.
  629.  */
  630. function map(func, ary) {
  631.  
  632.     /*
  633.      * WARNING: Caller assumnes responsibility to verify
  634.      * func and ary.
  635.      */
  636.  
  637.     for (var i in ary)
  638.         func(ary[i]);
  639.  
  640. }
  641.  
  642.